{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 项目： 基于评论的情感分析"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本项目的目标是基于用户提供的评论，通过算法自动去判断其评论是正面的还是负面的情感。比如给定一个用户的评论：\n",
    "- 评论1： “我特别喜欢这个电器，我已经用了3个月，一点问题都没有！”\n",
    "- 评论2： “我从这家淘宝店卖的东西不到一周就开始坏掉了，强烈建议不要买，真实浪费钱”\n",
    "\n",
    "对于这两个评论，第一个明显是正面的，第二个是负面的。 我们希望搭建一个AI算法能够自动帮我们识别出评论是正面还是负面。\n",
    "\n",
    "情感分析的应用场景非常丰富，也是NLP技术在不同场景中落地的典范。比如对于一个证券领域，作为股民，其实比较关注舆论的变化，这个时候如果能有一个AI算法自动给网络上的舆论做正负面判断，然后把所有相关的结论再整合，这样我们可以根据这些大众的舆论，辅助做买卖的决策。 另外，在电商领域评论无处不在，而且评论已经成为影响用户购买决策的非常重要的因素，所以如果AI系统能够自动分析其情感，则后续可以做很多有意思的应用。 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "情感分析是文本处理领域经典的问题。整个系统一般会包括几个模块：\n",
    "- 数据的抓取： 通过爬虫的技术去网络抓取相关文本数据\n",
    "- 数据的清洗/预处理：在本文中一般需要去掉无用的信息，比如各种标签（HTML标签），标点符号，停用词等等\n",
    "- 把文本信息转换成向量： 这也成为特征工程，文本本身是不能作为模型的输入，只有数字（比如向量）才能成为模型的输入。所以进入模型之前，任何的信号都需要转换成模型可识别的数字信号（数字，向量，矩阵，张量...)\n",
    "- 选择合适的模型以及合适的评估方法。 对于情感分析来说，这是二分类问题（或者三分类：正面，负面，中性），所以需要采用分类算法比如逻辑回归，朴素贝叶斯，神经网络，SVM等等。另外，我们需要选择合适的评估方法，比如对于一个应用，我们是关注准确率呢，还是关注召回率呢？ 这跟应用场景以及数据本身有关。比如训练数据里，有100个正样本，1个负样本，那这时候就不太适合用准确率来衡量系统的好坏，为什么？ 因为在这种样本很不均匀的情况下，我直接把所有的数据分类成正样本，那在没有任何学习的情况下准确率也可以达到100/101，接近100%，这显然是不太合理的。所以在这种情况我们更趋向于用其他的评估方式比如AUC。评估方式是影响系统的关键因素，因为任何的学习过程都是在不断地优化我们制定的评估方式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本次项目中，我们已经给定了训练数据和测试数据，它们分别是 train.positive.txt, train.negative.txt， test_combined.txt. 请注意训练数据和测试数据的格式不一样，详情请见文件内容。 整个项目你需要完成以下步骤：\n",
    "- 数据的读取以及清洗： 从给定的.txt中读取内容，并做一些数据清洗，这里需要做几个工作： （1） 文本的读取，需要把字符串内容读进来。 （2）去掉无用的字符比如标点符号，多余的空格，换行符等  （3） 分词 \n",
    "- 把文本转换成TF-IDF向量： 这部分直接可以利用sklearn提供的TfidfVectorizer类来做。\n",
    "- 利用逻辑回归模型来做分类，并通过交叉验证选择最合适的超参数\n",
    "- 利用神经网络，支持向量机做分类，并通过交叉验证选择神经网络的合适的参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第一部分： 数据预处理\n",
    "本部分你将要完成数据的预处理过程，包括数据的读取，数据清洗，分词，以及把文本转换成tf-idf向量。请注意: 在接下来的任务中，正面的情感我们标记为1， 负面\n",
    "的情感我们标记成0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "import jieba\n",
    "import numpy as np\n",
    "\n",
    "def process_line(line):   \n",
    "    new_line = re.sub('([a-zA-Z0-9])','',line)\n",
    "    new_line = ''.join(e for e in new_line if e.isalnum())\n",
    "    new_line = ','.join(jieba.cut(new_line))\n",
    "    return new_line\n",
    "    \n",
    "def process_train(file_path):\n",
    "    comments = []  # 用来存储评论\n",
    "    labels = []    # 用来存储标签（正/负），如果是train_positive.txt，则所有标签为1， 否则0. \n",
    "    with open(file_path) as file:\n",
    "        # TODO 提取每一个评论，然后利用process_line函数来做处理，并添加到comments。\n",
    "        text = file.read().replace(' ','').replace('\\n','')\n",
    "        reg = '<reviewid=.*?</review>'\n",
    "        result = re.findall(reg,text)\n",
    "        for r in result:\n",
    "            r = process_line(r)\n",
    "            comments.append(r)\n",
    "            if file_path == 'train.positive.txt':\n",
    "                labels.append('1')\n",
    "            else:\n",
    "                labels.append('0')\n",
    "    return comments, labels\n",
    "    \n",
    "    \n",
    "def process_test(file_path):\n",
    "    comments = []  # 用来存储评论\n",
    "    labels = []    # 用来存储标签(正/负).\n",
    "    with open(file_path) as file:\n",
    "        # TODO 提取每一个评论，然后利用process_line函数来做处理，并添加到\n",
    "        # comments。\n",
    "        text = file.read().replace(' ','').replace('\\n','')\n",
    "        reg = '<reviewid=.*?</review>'\n",
    "        result = re.findall(reg,text)\n",
    "        for r in result:\n",
    "            \n",
    "            label = re.findall('label=\"(\\d)\"',r)[0]\n",
    "            labels.append(label)\n",
    "            r = process_line(r)\n",
    "            comments.append(r)\n",
    "    return comments, labels\n",
    "    \n",
    "\n",
    "def read_file():\n",
    "    \"\"\"\n",
    "    读取所提供的.txt文件，并把内容处理之后写到list里面。 这里需要分别处理四个文件，“train_positive.txt\", \"train_negative.txt\",\n",
    "    \"test_combined.txt\" 并把每一个文件里的内容存储成列表。 \n",
    "    \"\"\"\n",
    "    # 处理训练数据，这两个文件的格式相同，请指定训练文件的路径\n",
    "    train_pos_comments, train_pos_labels = process_train(\"train.positive.txt\")\n",
    "    train_neg_comments, train_neg_labels = process_train(\"train.negative.txt\")\n",
    "    \n",
    "    # TODO: train_pos_comments和train_neg_comments合并成train_comments， train_pos_labels和train_neg_labels合并成train_labels\n",
    "    train_comments = train_pos_comments + train_pos_labels\n",
    "    train_labels = train_pos_labels + train_neg_labels\n",
    "    # 处理测试数据, 请指定测试文件的路径\n",
    "    test_comments, test_labels = process_test(\"test.combined.txt\")\n",
    "    \n",
    "    return train_comments, train_labels, test_comments, test_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache /var/folders/18/6srg07412v12cx1h90mpgggm0000gq/T/jieba.cache\n",
      "Loading model cost 1.311 seconds.\n",
      "Prefix dict has been built succesfully.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10000 10000 2500 2500\n"
     ]
    }
   ],
   "source": [
    "# 读取数据，并对文本进行处理\n",
    "train_comments, train_labels, test_comments, test_labels = read_file()\n",
    "\n",
    "# 查看训练数据与测试数据大小\n",
    "print (len(train_comments), len(train_labels), len(test_comments), len(test_labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 17659) (10000,) (2500, 17659) (2500,)\n"
     ]
    }
   ],
   "source": [
    "# 把每一个文本内容转换成tf-idf向量\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer  # 导入sklearn库\n",
    "# TODO: 利用TfidfVectorizer把train_comments转换成tf-idf，把结果存储在X_train, 这里X_train是稀疏矩阵（Sparse Matrix） \n",
    "# 并把train_labels转换成向量 y_train. 类似的，去创建X_test, y_test。 把文本转换成tf-idf过程请参考TfidfVectorizer的说明\n",
    "tfid_vec = TfidfVectorizer()\n",
    "X_train = tfid_vec.fit_transform(train_comments)\n",
    "y_train = np.array(train_labels)\n",
    "X_test = tfid_vec.transform(test_comments)\n",
    "y_test = np.array(test_labels)\n",
    "# 查看每个矩阵，向量的大小, 保证X_train和y_train, X_test和y_test的长度是一样的。\n",
    "print (np.shape(X_train), np.shape(y_train), np.shape(X_test), np.shape(y_test))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第二部分： 利用逻辑回归模型搭建情感分析引擎\n",
    "在本部分你将会利用罗回归模型（logistic regressiion）来搭建情感分析引擎。你需要完成整个pipeline的搭建过程，从而学会一个机器学习模型的搭建流程。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据上的准确率为：0.9585\n",
      "测试数据上的准确率为: 0.5248\n",
      "['这个,很,好']\n",
      "  (0, 15943)\t1.0\n",
      "['1']\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "# TODO： 初始化模型model，并利用模型的fit函数来做训练，暂时用默认的设置。\n",
    "# 具体使用方法请参考：http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html\n",
    "lr = LogisticRegression().fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(lr.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(lr.score(X_test, y_test)))\n",
    "\n",
    "# TODO： 打印混淆矩阵（confusion matrix）。\n",
    "# 参考：http://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html\n",
    "# 混淆矩阵是一种常用的分析方法。比如模型的准确率不理想的情况下，可以做进一步地分析，并找出原因。 在情感分析问题上，\n",
    "# 混淆矩阵可以用来分析有多少个原本正样本被分类成负样本，有多少原本是负样本的被分类成正样本，可以做这种精细化的结果分析，从而找到一些原因。 \n",
    "\n",
    "# TODO: 利用自己提出的例子来做测试。随意指定一个评论，接着利用process_line来做预处理，再利用之前构建好的TfidfVectorizer来把文本转换\n",
    "# 成tf-idf向量， 然后再利用构建好的model做预测（model.predict函数）\n",
    "test_comment1 = \"这个很好\"\n",
    "test_comment2 = \"垃圾\"\n",
    "test_comment3 = \"评论区说不烂都是骗人的，超赞\"\n",
    "\n",
    "a = []\n",
    "a.append(process_line(test_comment1))\n",
    "print(a)\n",
    "print(tfid_vec.transform(a))\n",
    "print(lr.predict(tfid_vec.transform(a)))\n",
    "\n",
    "# TODO: 输出结果，并自己分析一下是不是跟自己想象的结果一致。 也可以输出两个分类的概率\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第三部分： 利用决策树，神经网络，SVM来训练模型。 \n",
    "本部分类似于第二部分的内容，只不过替换成其他的模型（包括决策树，神经网络，SVM模型）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据上的准确率为：0.9929\n",
      "测试数据上的准确率为: 0.5212\n",
      "训练数据上的准确率为：0.6961\n",
      "测试数据上的准确率为: 0.572\n",
      "训练数据上的准确率为：0.741\n",
      "测试数据上的准确率为: 0.5776\n"
     ]
    }
   ],
   "source": [
    "# 利用决策树来做情感分析预测\n",
    "from sklearn import tree\n",
    "# 具体使用方法请参考：http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html\n",
    "\n",
    "# TODO: 初始化决策树模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，利用决策树默认的参数设置\n",
    "dtc1 = tree.DecisionTreeClassifier().fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(dtc1.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(dtc1.score(X_test, y_test)))\n",
    "\n",
    "\n",
    "# TODO: 初始化决策树模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，设置max_depth参数为3\n",
    "dtc2 = tree.DecisionTreeClassifier(max_depth=3).fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(dtc2.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(dtc2.score(X_test, y_test)))\n",
    "\n",
    "\n",
    "# TODO: 初始化决策树模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，设置max_depth参数为5\n",
    "dtc3 = tree.DecisionTreeClassifier(max_depth=5).fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(dtc3.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(dtc3.score(X_test, y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据上的准确率为：0.5155\n",
      "测试数据上的准确率为: 0.514\n"
     ]
    }
   ],
   "source": [
    "# 利用支持向量机（SVM）来做情感分析预测\n",
    "from sklearn import svm\n",
    "# http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html\n",
    "\n",
    "# TODO: 初始化SVM模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，SVM模型的kernel设置成“rbf”核函数\n",
    "svc = svm.SVC(kernel='rbf').fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(svc.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(svc.score(X_test, y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据上的准确率为：0.9929\n",
      "测试数据上的准确率为: 0.516\n"
     ]
    }
   ],
   "source": [
    "# 利用线性支持向量机(LinearSVM)来做情感分析的预测\n",
    "from sklearn.svm import LinearSVC\n",
    "# 具体的使用方式请见： http://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html\n",
    "\n",
    "# TODO: 初始化LinearSVC模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，使用模型的默认参数。\n",
    "clf = LinearSVC()\n",
    "clf.fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(clf.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(clf.score(X_test, y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据上的准确率为：0.9929\n",
      "测试数据上的准确率为: 0.4988\n"
     ]
    }
   ],
   "source": [
    "# 利用神经网络模型来做情感分析的预测\n",
    "from sklearn.neural_network import MLPClassifier\n",
    "# 具体使用方法请见：http://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html\n",
    "\n",
    "# TODO: 初始化MLPClassifier模型，并利用模型的fit函数来做训练并打印在训练和测试数据上的准确率，设置为hidden_layer_sizes为100，\n",
    "# 并使用\"lbfgs\" solver\n",
    "mlp = MLPClassifier(solver='lbfgs',hidden_layer_sizes=100)\n",
    "mlp.fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(mlp.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(mlp.score(X_test, y_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第四部分： 通过交叉验证找出最好的超参数\n",
    "调用一个sklearn模型本身很简单，只需要2行代码即可以完成所需要的操作。但这里的关键点在于怎么去寻找最优的超参数（hyperparameter）。 比如对于逻辑回归\n",
    "来说，我们可以设定一些参数的值如“penalty”, C等等，这些我们可以理解成是超参数。通常情况下，超参数对于整个模型的效果有着举足轻重的作用，这就意味着\n",
    "我们需要一种方式起来找到一个比较合适的参数。其中一个最常用的方法是grid search, 也就在一个去区间里面做搜索，然后找到最优的那个参数值。 \n",
    "\n",
    "举个例子，对于逻辑回归模型，它拥有一个超参数叫做C,在文档里面解释叫做“Inverse of regularization strength“， 就是正则的权重，而且这种权重的取值\n",
    "范围可以认为通常是（0.01, 1000）区间。这时候，通过grid search的方式我们依次可以尝试 0.01, 0.1, 1, 10, 100, 1000 这些值，然后找出使得\n",
    "模型的准确率最高的参数。当然，如果计算条件资源允许的话，可以尝试更多的值，比如0.01,0.05,0.1, 0.5, 1, 5, 10 ..。 当我们尝试越多值的时候，找到\n",
    "最优参数的概率就会越大。\n",
    "\n",
    "另外，参数的搜索过程离不开交叉验证，交叉验证相关的细节请参考线上的视频课程。\n",
    "\n",
    "在第四部分里，你将要编写程序来寻找最优的参数，分别针对逻辑回归和神经网络模型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最好的参数C值为： 1000.000000\n",
      "训练数据上的准确率为：0.9929\n",
      "测试数据上的准确率为: 0.5088\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.model_selection import KFold\n",
    "params_c = np.logspace(-3,3,7)   # 对于参数 “C”，尝试几个不同的值\n",
    "best_c = params_c[0]  # 存储最好的C值\n",
    "best_acc = 0\n",
    "kf = KFold(n_splits=5,shuffle=False)\n",
    "for c in params_c:\n",
    "    # TODO： 编写交叉验证的过程，对于每一个c值，计算出在验证集中的平均准确率。 在这里，我们做5-fold交叉验证。也就是，每一次把20%\n",
    "    #   的数据作为验证集来对待，然后准确率为五次的平均值。我们把这个准确率命名为 acc_avg\n",
    "    avg = 0\n",
    "    for train_index, test_index in kf.split(X_train):\n",
    "        lr = LogisticRegression(C=c).fit(X_train[train_index],y_train[train_index])\n",
    "        avg += lr.score(X_train[test_index],y_train[test_index])\n",
    "    acc_avg = avg/5\n",
    "    if acc_avg > best_acc:\n",
    "        best_acc = acc_avg\n",
    "        best_c = c\n",
    "\n",
    "print (\"最好的参数C值为： %f\" % (best_c))\n",
    "# TODO 我们需要在整个训练数据上重新训练模型，但这次利用最好的参数best_c值\n",
    "#     提示： model = LogisticRegression(C=best_c).fit(X_train, y_train)\n",
    "lr = LogisticRegression(C=best_c).fit(X_train, y_train)\n",
    "\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(lr.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(lr.score(X_test, y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.neural_network import MLPClassifier\n",
    "import numpy as np\n",
    "\n",
    "param_hidden_layer_sizes = np.linspace(10, 200, 20)  # 针对参数 “hidden_layer_sizes”, 尝试几个不同的值\n",
    "param_alphas = np.logspace(-4,1,6)  # 对于参数 \"alpha\", 尝试几个不同的值\n",
    "\n",
    "best_hidden_layer_size = param_hidden_layer_sizes[0]\n",
    "best_alpha = param_alphas[0]\n",
    "\n",
    "for size in param_hidden_layer_sizes:\n",
    "    for val in param_alphas:\n",
    "        # TODO 编写交叉验证的过程，需要做5-fold交叉验证。\n",
    "        avg = 0\n",
    "        for train_index, test_index in kf.split(X_train, y_train):\n",
    "            mlp = MLPClassifier(alpha=int(val),hidden_layer_sizes=int(size))\n",
    "            mlp.fit(X_train[train_index],y_train[train_index])\n",
    "            avg += mlp.score(X_train[test_index],y_train[test_index])\n",
    "        acc_avg = avg/5\n",
    "        if acc_avg > best_acc:\n",
    "            best_acc = acc_avg\n",
    "            best_hidden_layer_size = size\n",
    "            best_alpha = val\n",
    "\n",
    "print (\"最好的参数hidden_layer_size值为： %f\" % (best_hidden_layer_size))\n",
    "print (\"最好的参数alpha值为： %f\" % (best_alpha))\n",
    "\n",
    "# TODO 我们需要在整个训练数据上重新训练模型，但这次使用最好的参数hidden_layer_size和best_alpha\n",
    "mlp = MLPClassifier(alpha=best_alpha,hidden_layer_sizes=best_hidden_layer_size).fit(X_train,y_train)\n",
    "# 打印在训练数据上的准确率\n",
    "print (\"训练数据上的准确率为：\" + str(mlp.score(X_train, y_train)))\n",
    "\n",
    "# 打印在测试数据上的准确率\n",
    "print (\"测试数据上的准确率为: \" + str(mlp.score(X_test, y_test)))            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
